# coding:utf-8
# 山石网科
import paramiko
import re
from os import devnull
from network.base_connection import BaseConnection
from network.CustomizedException import *
paramiko.util.log_to_file(devnull, level=paramiko.common.WARNING)


class Hillstone(BaseConnection):

    """创建和销毁ssh会话"""

    def _set_pagination_param(self):
        """
        设置设备分页相关的默认参数，若用户指定了相关参数，则优先使用用户设置的参数
        分页标识符仅在每次从缓冲区读取的命令回显的最后一行中查找
        """
        if not self.no_pagination_cmd:
            self.no_pagination_cmd = "terminal length 0"
        if self.logger:
            self.logger.debug(f"no_pagination_cmd:`{self.no_pagination_cmd}`")
        if not self.pagination_pattern:
            self.pagination_pattern = re.compile(r"--More--")
        if self.logger:
            self.logger.debug(f"pagination_pattern:`{self.pagination_pattern}`")
        if not self.next_page_cmd:
            self.next_page_cmd = " "
        if self.logger:
            self.logger.debug(f"next_page_cmd:`{self.next_page_cmd}`")

    def _set_prompt_patterns(self):
        """
        设置已知的命令提示符正则模式元组
        命令提示符仅在每次从缓冲区读取的命令回显的最后一行中查找
        """
        patterns = {
            re.compile(r"^\S+#\s*$"),
            re.compile(r"\[y]/n:\s*$"),
            re.compile(r"password:\s*$"),
        }
        if self.pagination_pattern:
            patterns.add(self.pagination_pattern)
        if self.prompt_patterns:
            patterns.update(self.prompt_patterns)
        self.prompt_patterns = patterns
        if self.logger:
            self.logger.debug(f"prompt_patterns:{self.prompt_patterns}")

    def _set_error_patterns(self):
        """
        设置已知的命令错误提示正则模式元组
        错误提示符会在命令回显的每行中查找，所以需要修饰符re.M
        """
        patterns = {
            re.compile(r"^\s*-----\^unrecognized keyword", flags=re.M),
            re.compile(r"^Error:", flags=re.M)
        }
        if self.error_patterns:
            patterns.update(self.error_patterns)
        self.error_patterns = patterns
        if self.logger:
            self.logger.debug(f"error_patterns:{self.error_patterns}")

    """视图切换"""

    def change_mode(self, mode):
        """
        更改命令模式
        :param str mode:命令模式，可选参数：user|enable|config
        user    用户视图
        enable  特权视图
        config  全局配置视图
        """
        if mode == "user":
            msg = "Hillstone dose not support mode `user`, the valid mode is `enable` or `config`"
            if self.logger:
                self.logger.warning(msg)
            raise UnSupportedException(msg)
        elif mode == "enable":
            try:
                self.shell("end")
            except CommandExecuteException:
                pass
            if self.logger:
                self.logger.info(f"change mode to {mode}")
        elif mode == "config":
            try:
                self.shell("end")
            except CommandExecuteException:
                pass
            self.shell("configure")
            if self.logger:
                self.logger.info(f"change mode to {mode}")
        else:
            msg = "unknown mode `{}`, the valid mode is `enable` or `config`".format(mode)
            if self.logger:
                self.logger.warning(msg)
            raise UnSupportedException(msg)

    """配置保存"""

    def save(self):
        """保存配置"""
        try:
            # 切换至特权视图
            self.change_mode(mode="enable")
            # 保存配置
            self.shell(cmd="save all")
            self.shell("y")
            self.shell("y")
            if self.logger:
                self.logger.info("save configuration success")
        except Exception as e:
            if self.logger:
                self.logger.error(f"save configuration failure:{str(e)}")
            raise ConfigSaveException(str(e))

    """扩展功能"""

    @property
    def platform(self):
        """
        获取设备平台(操作系统)类型, 获取不到则返回None
        """
        # 获取平台类型（操作系统类型）
        if not hasattr(self, "__platform"):
            self.__platform = None
            res = self.shell("show version")
            patterns = [
                re.compile(r"^Hillstone Networks (\S+) software, Version", re.M),
            ]
            for pattern in patterns:
                platform = pattern.findall(res)
                if platform:
                    self.__platform = platform[0]
                    break
        if self.logger:
            self.logger.debug(f"return __platform: {self.__platform}")
        return self.__platform



